/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#ifndef M_LFSTACK_H
#define M_LFSTACK_H

#include "lfprimitives.h"
#ifdef _MSC_VER
#pragma warning(disable: 4127) // conditional expression is constant
#endif

namespace Engine
{
	namespace LockFree
	{
		/**
		*   Class represent stack container with lock free synchronization.
		*/
		template<typename T>
		class Stack
		{
		public:
			/**
			*   Constructor.
			*/
			Stack() : m_pHead(0), m_cPops(0) {}

			/**
			*   Push new node.
			*/
			void Push(node<T> * pNode);

			/**
			*   Pop top of stack.
			*/
			node<T> * Pop();
		private:
			node<T> * volatile m_pHead; ///< pointer to head(top) node in container.
			volatile uint32_t  m_cPops; ///< number of pop calls, used for synchronization.
		};
		/*************************************************************************************************/
		template<typename T>
		void Stack<T>::Push(node<T> * pNode)
		{
			while(true)
			{
				pNode->pNext = m_pHead;
				if(CAS(&m_pHead, pNode->pNext, pNode))
				{
					break;
				}
			}
		}
		/*************************************************************************************************/
		template<typename T>
		node<T> * Stack<T>::Pop()
		{
			while(true)
			{
				node<T> * pHead = m_pHead;
				uint32_t  cPops = m_cPops;
				if(0 == pHead)
				{
					return 0;
				}

				node<T> * pNext = pHead->pNext;
				if(CAS2(&m_pHead, pHead, cPops, pNext, cPops + 1))
				{
					return pHead;
				}
			}
		}
		/*************************************************************************************************/
	}
}

#endif
